/**
 * 反射工具类
 */
package com.cnfangmao.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;


public class ReflectUtil {
	private static Logger logger=Logger.getLogger(ReflectUtil.class);
	
	private final static Class<?>[] PROTOTYPES= {
			java.lang.Integer.class,
			java.lang.Byte.class,
			java.lang.Long.class,
			java.lang.Double.class,
			java.lang.Float.class,
			java.lang.Character.class,
			java.lang.Short.class,
			java.lang.Boolean.class,
			java.lang.String.class,
			java.util.Date.class,
			int.class,
			byte.class,
			long.class,
			double.class,
			float.class,
			short.class,
			boolean.class,
			String.class
	};
	
	/****
	 * 判断一个变量其值类型是否为java原生数据类型
	 * @param value
	 * @return
	 */
	public static boolean isProtoType(Class<?> clazz)
	{
		boolean bResult=false;
		
		for(Class<?> item:PROTOTYPES)
		{
			if(item.equals(clazz))
			{
				bResult=true;
				break;
			}
		}
		
		return bResult;
	}

	/*****
	 * 判断一个类是否被一个注解注释过
	 * @param clazz  类
	 * @param annotation 注解
	 * @return
	 */
	public static boolean isAnnotationPresent(Class<?> clazz,Class<? extends Annotation> annotation)
	{
		return clazz.isAnnotationPresent(annotation);
	}
	
	/*****
	 * 判断一个字段是否被一个注解注释过
	 * @param field  字段
	 * @param annotation 注解
	 * @return
	 */
	public static boolean isAnnotationPresent(Field field,Class<? extends Annotation> annotation)
	{
		return field.isAnnotationPresent(annotation);
	}

	/****
	 * 得到一个类及其父类祖先类所有声明的字段
	 * @param clazz
	 * @return
	 */
	public static List<Field> getAllFields(Class<?> clazz)
	{
		List<Field> lstField=new LinkedList<Field>();
		
		Class<?> currentClazz=clazz;
		while(currentClazz!=null)
		{
			lstField.addAll(Arrays.asList(currentClazz.getDeclaredFields()));
			currentClazz=currentClazz.getSuperclass();
		}
		
		return lstField;
	}
	
	/****
	 * 得到一个类祖先类所有声明的字段
	 * @param clazz
	 * @return
	 */
	public static List<Field> getDeclaringFields(Class<?> clazz)
	{
		List<Field> lstField=new LinkedList<Field>();
		
		lstField.addAll(Arrays.asList(clazz.getDeclaredFields()));

		return lstField;
	}	

	/****
	 * 得到一个类及其父类祖先类所有声明的方法
	 * @param clazz
	 * @return
	 */
	public static List<Method> getAllMethods(Class<?> clazz)
	{
		List<Method> lstMethod=new LinkedList<Method>();
		
		Class<?> currentClazz=clazz;
		while(currentClazz!=null)
		{
			lstMethod.addAll(Arrays.asList(currentClazz.getDeclaredMethods()));
			currentClazz=currentClazz.getSuperclass();
		}
		
		return lstMethod;
	}
	
	/***
	 * 得到一个类被指定注解过的所有属性
	 * @param clazz
	 * @param annotation
	 * @return
	 */
	public static List<Field> getAnnotationFields(Class<?> clazz,Class<? extends Annotation> annotation )
	{
		List<Field> lstField=new LinkedList<Field>();

		for(Field field:getAllFields(clazz))
		{
			if(field.getDeclaredAnnotation(annotation)!=null) {
				lstField.add(field);
			}
		}
		return lstField;
	}

	/***
	 * 得到一个类被指定注解过的所有方法
	 * @param clazz
	 * @param annotation
	 * @return
	 */
	public static List<Method> getAnnotationMethods(Class<?> clazz,Class<Annotation> annotation )
	{
		List<Method> lstMethod=new LinkedList<Method>();

		for(Method method:getAllMethods(clazz))
		{
			if(method.getDeclaredAnnotation(annotation)!=null) {
				lstMethod.add(method);
			}
		}
		return lstMethod;
	}

	/****
	 * 判断一个类是否为数组
	 * @param clazz
	 * @return
	 */
	public static boolean isArray(Class<?> clazz)
	{
		return clazz.isArray();
	}

	/****
	 * 判断一个类是否为集合
	 * @param clazz
	 * @return
	 */
	public static boolean isCollection(Class<?> clazz)
	{
		return Collection.class.isAssignableFrom(clazz);
	}

	/****
	 * 判断一个类是否为集合
	 * @param clazz
	 * @return
	 */
	public static boolean isList(Class<?> clazz)
	{
		return List.class.isAssignableFrom(clazz);
	}
	
	/****
	 * 判断一个类是否为集合
	 * @param clazz
	 * @return
	 */
	public static boolean isSet(Class<?> clazz)
	{
		return Set.class.isAssignableFrom(clazz);
	}
	
	/****
	 * 判断一个类是否为Map
	 * @param clazz
	 * @return
	 */
	public static boolean isMap(Class<?> clazz)
	{
		return Map.class.isAssignableFrom(clazz);
	}
	
	/****
	 * 两个类是否相等
	 * @param left
	 * @param right
	 * @return
	 */
	public static boolean isEqual(Class<?> left,Class<?> right)
	{
		return left.equals(right);
	}
	
	/****
	 * 判断一个字段是否为final字段
	 * @param field
	 * @return
	 */
	public static boolean isFinal(Field field)
	{
		return Modifier.isFinal(field.getModifiers());
	}
	
	/****
	 * 判断一个字段是否为public字段
	 * @param field
	 * @return
	 */
	public static boolean isPublic(Field field)
	{
		return Modifier.isPublic(field.getModifiers());
	}	
	
	/****
	 * 判断一个字段是否为private字段
	 * @param field
	 * @return
	 */
	public static boolean isPrivate(Field field)
	{
		return Modifier.isPrivate(field.getModifiers());
	}	
	
	/****
	 * 判断一个字段是否为private字段
	 * @param field
	 * @return
	 */
	public static boolean isStatic(Field field)
	{
		return Modifier.isStatic(field.getModifiers());
	}	

	/***
	 * 得到指定名字的字段名
	 * @param clazz
	 * @param fieldName
	 * @return
	 */
	public static Field getField(Class<?> clazz,String fieldName)
	{
		try {
			List<Field> fields=getAllFields(clazz);
			for(Field field:fields)
			{
				if(StringUtils.equals(field.getName(), fieldName))
				{
					return field;
				}
			}
			return null;
		} catch (Exception e) {
			logger.error(e);
		}
		return null;
	}
	
	/****
	 * 得到方法的属性值
	 * @param method
	 * @param attr
	 * @return
	 */
	public static Object getAttribute(Method method,Class<? extends Annotation> annotation,String attr)
	{
		Object result=null;
		Annotation anno=method.getDeclaredAnnotation(annotation);
		try {
			Class<?>[] parameterType= {};
			Method paraMethod=anno.getClass().getDeclaredMethod(attr, parameterType);
			Object[] values= {};
			result=paraMethod.invoke(anno, values);
		} catch (Exception e) {
			logger.error(e);
		}
		
		return result;
	}
	
	/*****
	 * 得到一个对象某个字段的值
	 * @param entity
	 * @param fieldname
	 * @return
	 */
	public static Object getFieldValue(Object entity,String fieldname)
	{
		Object value=null;
		
		if(entity!=null)
		{
			Field field=getField(entity.getClass(),fieldname);
			if(field!=null)
			{
				field.setAccessible(true);
				try {
					value=field.get(entity);
				} catch (Exception e) {
					logger.error(e);
				}
			}
		}
		return value;
	}
	
	/*****
	 * 设置一个对象某个字段的值
	 * @param entity
	 * @param fieldname
	 * @return
	 */
	public static void setFieldValue(Object entity,String fieldname,Object objValue)
	{
		if(entity!=null)
		{
			Field field=getField(entity.getClass(),fieldname);
			if(field!=null)
			{
				field.setAccessible(true);
				try {
					field.set(entity,objValue);
				} catch (Exception e) {
					//			logger.error(e);
				}
			}
		}
	}
	
}
